#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#if defined(TEST_TARGET_date)
#include <varch/command.h>
#include <varch/unitt.h>
#include <varch/date.h>
#else  
#include "init.h"
#include "command.h"
#include "unitt.h"
#include "kern.h"
#include "date.h"
#endif

/************************************************************************************/
/************************************* Unit Test ************************************/
/************************************************************************************/

/************************************************************************************/
/************************************* Base Test ************************************/
/************************************************************************************/

static void test_base(void)
{
    printf("month days %d\r\n", date_month_days(2024, 11));
    printf("date_isleap %d\r\n", date_isleap(1582));
    // printf("date_current_days %d\r\n", date_current_days(DATE(1,1,1)));
    // printf("date_current_days %d\r\n", date_current_days(DATE(2000,12,31)));
    // printf("date_current_days %d\r\n", date_current_days(DATE(2001,1,1)));
    // printf("date_current_days %d\r\n", date_current_days(DATE(2024,11,9)));
    printf("date_get_dow %d\r\n", date_get_dow(DATE(2024,11,11)));

    printf("date_diff_days %d\r\n", date_diff_days(DATE(2018,3,14), DATE(2024,11,10)));

    // DATE date = date_from_days(date_current_days(DATE(2024,11,30)));
    DATE date = date_offset(DATE(2024,11,30), -1);

    printf("%d.%d.%d\r\n", date.year,date.month,date.day);

    date_calendar(1998,7);
    date_calendar(2024,11);
    date_calendar(2224,11);
}

/************************************************************************************/
/*************************************  Command  ************************************/
/************************************************************************************/

static void usage(void)
{
    printf(
"Usage: date [opt] [arg] ...\n"
"\n"
"options:\n"
"    -e <execute>        Specifies the function to execute, the default is the base test\n"
"                        <base>      Test base function\n"
"                        <calendar>  Show the calendar for a specific month and year\n"
"                        <leap>      Check if a year is a leap year\n"
"                        <valid>     Validate a date\n"
"                        <dow>       Get the day of week of a given date based on the total days\n"
"                        <diff>      Calculate the difference in days between two dates\n"
"    -h                  Print help\n"
"    -v                  Print version\n"
"    -y <year>           Year\n"
"    -m <month>          Month\n"
"    -d <day>            Day\n"
"\n"
    );
}

static int test(int argc, char *argv[])
{
    char *execute = NULL;
    DATE date[2] = {0};
    int iy = 0, im = 0, id = 0;

    /* reset getopt */
    command_opt_init();

    while (1)
    {
        int opt = command_getopt(argc, argv, "e:hvu::y:m:d:");
        if (opt == -1) break;

        switch (opt) 
        {
        case 'y' :
            if (iy < 2) date[iy++].year = atoi(command_optarg);
            break;
        case 'm' :
            if (im < 2) date[im++].month = atoi(command_optarg);
            break;
        case 'd' :
            if (id < 2) date[id++].day = atoi(command_optarg);
            break;
        case 'e' :
            execute = command_optarg;
            break;
        case 'v' :
            printf("date version %d.%d.%d\r\n", DATE_V_MAJOR, DATE_V_MINOR, DATE_V_PATCH);
            return 0;
        case '?':
            printf("Unknown option `%c`\r\n", command_optopt);
            return -1;
        case 'h' : 
        default:
            usage();
            return 0;
        }
    }

    if (execute)
    {
        if (!strcmp(execute, "base"))
        {
            test_base();
        }
        else if (!strcmp(execute, "calendar"))
        {
            date_calendar(date[0].year, date[0].month);
        }
        else if (!strcmp(execute, "leap"))
        {
            printf("%d %s leap year!\r\n", date[0].year, date_isleap(date[0].year) ? "is" : "isn't");
        }
        else if (!strcmp(execute, "valid"))
        {
            printf("%04u.%02u.%02u %s valid!\r\n", date[0].year, date[0].month, date[0].day, date_isleap(date[0].year) ? "is" : "isn't");
        }
        else if (!strcmp(execute, "dow"))
        {
            const char *dow[] = {
                "Invalid", 
                "Monday",
                "Tuesday",
                "Wednesday",
                "Thursday",
                "Friday",
                "Saturday",
                "Sunday",
            };
            printf("%04u.%02u.%02u is %s!\r\n", date[0].year, date[0].month, date[0].day, 
                dow[date_get_dow(date[0])]);
        }
        else if (!strcmp(execute, "diff"))
        {
            printf("%04u.%02u.%02u is %d days away from %04u.%02u.%02u!\r\n", 
                date[0].year, date[0].month, date[0].day, 
                date_diff_days(date[0], date[1]),
                date[1].year, date[1].month, date[1].day);
        }
    }
    else  
    {
        test_base();
    }
    
    return 0;
}

/************************************************************************************/
/************************************ Test entry ************************************/
/************************************************************************************/

#if defined(TEST_TARGET_date)
int main(int argc, char *argv[])
{
    return test(argc, argv);
}
#else 
void test_date(void)
{
    command_export("date", test);
}
init_export_app(test_date);
#endif 
